using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
using SubversionReports.Entities;
using SubversionReports.Utilities;

namespace SubversionReports.Web.Controls
{
    public partial class AuthorActivityGraph : UserControl
    {
        private SortableDictionary<string, int> authorChanges;
        private SortableDictionary<string, int> authorCommits;
        private int top = 0;
        private Repository repository;

        private DateTime startDate;
        private DateTime endDate;

        /// <summary>
        /// Gets the repository.
        /// </summary>
        /// <value>The repository.</value>
        protected Repository Repository
        {
            get
            {
                if (repository == null)
                    repository = SvnWebDav.GetRepositoryLog(SvnWebDav.CurrentRepositoryRootUrl, SvnWebDav.CurrentRepositoryUsername, SvnWebDav.CurrentRepositoryPassword).Filter("Date", StartDate, EndDate, FilterType.Include);
                return repository;
            }
        }

        /// <summary>
        /// Gets the top.
        /// </summary>
        /// <value>The top.</value>
        protected int Top
        {
            get
            {
                if (top.Equals(0))
                    foreach (KeyValuePair<string, int> pair in AuthorChanges)
                        if (top.Equals(0)) top = pair.Value;
                return top;
            }
        }

        /// <summary>
        /// Gets or sets the start date.
        /// </summary>
        /// <value>The start date.</value>
        protected DateTime StartDate
        {
            get
            {
                if(startDate == new DateTime() && !DateTime.TryParse(Request["StartDate"], out startDate))
                    startDate = DateTime.Now.AddDays(-7);
                return startDate;
            }
            set { startDate = value; }
        }

        /// <summary>
        /// Gets or sets the end date.
        /// </summary>
        /// <value>The end date.</value>
        protected DateTime EndDate
        {
            get
            {
                if (endDate == new DateTime() && !DateTime.TryParse(Request["EndDate"], out endDate))
                    endDate = DateTime.Now.AddHours(1);
                return endDate;
            }
            set { endDate = value; }
        }

        /// <summary>
        /// Gets the author changes.
        /// </summary>
        /// <value>The author changes.</value>
        protected SortableDictionary<string, int> AuthorChanges
        {
            get
            {
                if (authorChanges == null) authorChanges = Repository.AuthorChanges;
                authorChanges.Sort(delegate(KeyValuePair<string, int> pair1, KeyValuePair<string, int> pair2) { return pair2.Value.CompareTo(pair1.Value); });
                return authorChanges;
            }
        }

        /// <summary>
        /// Gets the author commits.
        /// </summary>
        /// <value>The author commits.</value>
        protected SortableDictionary<string, int> AuthorCommits
        {
            get
            {
                if (authorCommits == null)
                    authorCommits = Repository.AuthorCommits;
                return authorCommits;
            }
        }

        /// <summary>
        /// Gets the padding.
        /// </summary>
        /// <param name="changeCount">The change count.</param>
        /// <param name="top">The top.</param>
        /// <returns></returns>
        protected static string GetPadding(int changeCount, double top)
        {
            int maxPadding = 10;
            double padding = (changeCount / top) * maxPadding;
            return (changeCount > 0) ? string.Format("{0:0.0000}", padding) : 0.ToString();
        }

        /// <summary>
        /// Handles the Load event of the Page control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            if (Visible && SvnWebDav.AuthenticationSuceeded && !IsPostBack && !Page.IsCallback)
            {
                RepositoryTitle.Text = Repository.Url;
                RepositoryDescription.Text = Repository.Description;

                ActiveAuthorsTodayGridView.DataSource = AuthorChanges;
                ActiveAuthorsTodayGridView.DataBind();

                string urlFormat = "{0}?StartDate={1}&EndDate={2}";

                //DatePresets.Items.Add(new ListItem("Last 24 Hours", string.Format(urlFormat, Request.FilePath, GetUnixDate(DateTime.Now.AddDays(-1)), GetUnixDate(DateTime.Now))));
                //DatePresets.Items.Add(new ListItem("Last 48 Hours", string.Format(urlFormat, Request.FilePath, GetUnixDate(DateTime.Now.AddDays(-2)), GetUnixDate(DateTime.Now))));
                //DatePresets.Items.Add(new ListItem("Last 7 Days", string.Format(urlFormat, Request.FilePath, GetUnixDate(DateTime.Now.AddDays(-7)), GetUnixDate(DateTime.Now))));

                DatePresets.Items.Add(new ListItem("Today", string.Format(urlFormat, Request.FilePath, GetUnixDate(GetToday()), GetUnixDate(GetToday().AddDays(1).AddSeconds(-1)))));
                DatePresets.Items.Add(new ListItem("Yesterday", string.Format(urlFormat, Request.FilePath, GetUnixDate(GetToday().AddDays(-1)), GetUnixDate(GetToday().AddSeconds(-1)))));

                DatePresets.Items.Add(new ListItem("This Week", string.Format(urlFormat, Request.FilePath, GetUnixDate(GetFirstDayOfCurrentWeek()), GetUnixDate(GetFirstDayOfCurrentWeek().AddDays(7).AddSeconds(-1)))));
                DatePresets.Items.Add(new ListItem("Last Week", string.Format(urlFormat, Request.FilePath, GetUnixDate(GetFirstDayOfCurrentWeek().AddDays(-7)), GetUnixDate(GetFirstDayOfCurrentWeek().AddSeconds(-1)))));

                DatePresets.Items.Add(new ListItem("This Month", string.Format(urlFormat, Request.FilePath, GetUnixDate(GetFirstDayOfCurrentMonth()), GetUnixDate(GetFirstDayOfCurrentMonth().AddMonths(1).AddSeconds(-1)))));
                DatePresets.Items.Add(new ListItem("Last Month", string.Format(urlFormat, Request.FilePath, GetUnixDate(GetFirstDayOfCurrentMonth().AddMonths(-1)), GetUnixDate(GetFirstDayOfCurrentMonth().AddSeconds(-1)))));

                DatePresets.Items.Add(new ListItem("Since the dawn of man", string.Format(urlFormat, Request.FilePath, GetUnixDate(DateTime.MinValue), GetUnixDate(GetToday().AddDays(1).AddSeconds(-1)))));
            }
        }

        /// <summary>
        /// Gets the unix date.
        /// </summary>
        /// <param name="date">The date.</param>
        /// <returns></returns>
        private static string GetUnixDate(DateTime date)
        {
            return date.ToString("yyyy-MM-dd HH:mm:ss");
        }

        /// <summary>
        /// Gets todays date.
        /// </summary>
        /// <returns></returns>
        private static DateTime GetToday()
        {
            return new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
        }

        /// <summary>
        /// Gets the first day of current week.
        /// </summary>
        /// <returns></returns>
        private static DateTime GetFirstDayOfCurrentWeek()
        {
            DateTime date = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
            while (!date.DayOfWeek.Equals(DayOfWeek.Sunday))
                date = date.AddDays(-1);
            return date;
        }

        /// <summary>
        /// Gets the first day of current month.
        /// </summary>
        /// <returns></returns>
        private static DateTime GetFirstDayOfCurrentMonth()
        {
            DateTime date = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
            while (!date.Day.Equals(1))
                date = date.AddDays(-1);
            return date;
        }

        /// <summary>
        /// Gets the author icon URL.
        /// </summary>
        /// <param name="author">The author.</param>
        /// <returns></returns>
        protected string GetAuthorIconUrl(string author)
        {
            return Repository.AuthorIcons[author];
        }
    }
}